package org.ruoyi;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.CanvasFrame;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.BinaryMessage;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.imageio.ImageIO;
import javax.websocket.server.ServerEndpoint;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * @projectName: intelligent-monitor
 * @package: org.ruoyi
 * @className: VideoStreamHandler
 * @author: 寇耕耀
 */
@Component
@ServerEndpoint(value = "/videoStream")
public class VideoStreamHandler extends TextWebSocketHandler {

    private final CanvasFrame previewCanvas = new CanvasFrame("摄像头预览");
    private final Java2DFrameConverter converter = new Java2DFrameConverter();
    private List<Frame> frameList;
    private List<BufferedImage> bufferedImages;

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("连接结束");
//        record(frameList);
        System.out.println(recordImage(bufferedImages, 0L));
        session.close();
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
//        System.out.println();
        System.out.println(LocalDateTime.now());
        System.out.println("收到1回应数据" + message);
        // 这里可以处理接收到的文本消息，但在这个场景下可以忽略
    }

    private void init() {
        bufferedImages = new ArrayList<>();
        frameList = new ArrayList<>();
        previewCanvas.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        previewCanvas.setVisible(true);
        previewCanvas.setAlwaysOnTop(true);
    }


    @Override
    protected void handleBinaryMessage(WebSocketSession session, BinaryMessage message) {
//        System.out.println(LocalDateTime.now());
//        frameList.add(converter.getFrame(byteArrayToImage(message.getPayload().array())));
        BufferedImage image = byteArrayToImage(message.getPayload().array());
//        Frame frame = converter.getFrame(byteArrayToImage(message.getPayload().array()));
//        System.out.println(frame);
        System.out.println("收到2回应数据" + message.getPayload().array());
        bufferedImages.add(image);
        // 如果图像转换成功，则将其转换为Frame对象

        previewCanvas.showImage(image);
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        System.out.println("连接开始");
        session.sendMessage(new TextMessage("start"));
        init();
        // 连接建立后，可以在这里准备接收流数据
    }


    private BufferedImage byteArrayToImage(byte[] bytes) {
        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
        // 使用 ImageIO 读取 InputStream 并创建 BufferedImage
        BufferedImage bufferedImage = null;
        try {
            bufferedImage = ImageIO.read(bais);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bufferedImage;
    }

    private String recordImage(List<BufferedImage> imageList, Long id) throws IOException, InterruptedException {
        System.out.println("record调用");
        System.out.println("收到List:" + imageList);
        if (imageList == null || imageList.isEmpty()) {
            return null;
        }
        System.out.println("record记录");
        String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        String fileName = id + "&" + time + ".mp4";

//        设置视频参数:mp4,30帧
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("E:\\" + fileName, imageList.get(0).getWidth(), imageList.get(0).getHeight());
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        recorder.setFrameRate(24);
        recorder.start();


//        将每一帧写入到MP4文件中
        for (BufferedImage image : imageList) {
            recorder.record(converter.getFrame(image));
        }

//        停止录制并释放资源
        recorder.stop();
        recorder.release();

        Thread.sleep(2000);

//        return AliOssUtils.uploadFile(fileName, Files.newInputStream(Paths.get("E:\\" + fileName)));
        return 1 + "";
    }

    private String record(List<Frame> frameList, Long id) throws IOException, InterruptedException {
        System.out.println("record调用");
        System.out.println("收到FrameList:" + frameList);
        if (frameList == null || frameList.isEmpty()) {
            return null;
        }
        System.out.println("record记录");
        long time = System.currentTimeMillis();
        String fileName = time + ".mp4";

//        设置视频参数:mp4,30帧
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder("E:\\" + fileName, frameList.get(0).imageWidth, frameList.get(0).imageHeight);
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setFormat("mp4");
        recorder.setFrameRate(60);
        recorder.start();


//        将每一帧写入到MP4文件中
        for (Frame frame : frameList) {
            recorder.record(frame);
        }

//        停止录制并释放资源
        recorder.stop();
        recorder.release();

        Thread.sleep(2000);

//        return AliOssUtils.uploadFile(fileName, Files.newInputStream(Paths.get("E:\\" + fileName)));
        return "";
    }
}
